package cn.dwong.msgGateway.service;

import cn.dwong.msgGateway.entity.TitleContent;
import com.google.common.util.concurrent.RateLimiter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * @author 73202
 * @date 2022/3/10 13:19
 */
@Service
public class GatewayService {
    /**
     * 短信平台模拟器对于消息网关请求的限流规则如下：
     * 1、接口调用频率限流，每秒最多允许10个请求 。
     * 2、手机号码限流，每个手机号码每秒只能发送一次消息 。
     * 3、违反上述两条规则任何一条，短信平台将拒绝消息网关任意请求3秒。
     */
    private final Logger log = LoggerFactory.getLogger(GatewayService.class);
    @Autowired
    private MessageService messageService;
    @Autowired
    private RedisOperator redisOperator;

    //全局限流器（限制QPS为10）
    private static final RateLimiter r = RateLimiter.create(10);
    private static final  ExecutorService exec = Executors.newFixedThreadPool(200);

    /**
     * 接口调用限流
     */
    public String requestRateLimiterThreadPool(String tels, String qos,String sessionId, TitleContent titleContent){
        r.acquire();
        //多线程调用手机号码限流接口
        Future<String> future = exec.submit(new SendCallable(tels,qos,sessionId,titleContent));
        String resCode = null;
        try {
            resCode = future.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
            resCode = null;
        } catch (ExecutionException e) {
            e.printStackTrace();
            resCode = null;
        }
        return resCode;
    }

    public String requestRateLimiter(String tels, String qos,String sessionId, TitleContent titleContent){
        r.acquire();
        return sendMsgByTelRateLimiter(tels,qos,sessionId,titleContent);
    }

    /**
     * 手机号码限流：可以使用redis的sex指令+设置过期时间实现
     */
    public String sendMsgByTelRateLimiter(String tels,String qos,String sessionId, TitleContent titleContent){
        while(!redisOperator.setNx(tels,sessionId,1200)){
        }
        //调用发送短信的接口
        return messageService.sendMsg(qos,tels,titleContent);
    }
}


